﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Web.Mvc;
using FaceSharp.Api.Extensions;
using Newtonsoft.Json.Linq;
using RestSharp;

namespace FaceSharp.Api.GraphApi
{
    public class GenericGraphClient
    {      
        private readonly IFacebookCore _facebookCore;
        public GenericGraphClient(IFacebookCore facebookCore)
        {
            _facebookCore = facebookCore;
        }

        public GraphResult<T> GetMetaData<T>(
            string id,
            Func<string,T> graphResultConverter
            )
        {
            return BaseGraphRequest(
                id, 
                new Dictionary<string, string> { { "metadata", "1" } },
                graphResultConverter
                );
        }

        public GraphResult<T> MakeGraphPost<T>(
         string id,
         Dictionary<string, string> parameters,
         Func<string,T> graphResultConverter
         )
        {
            return BaseGraphRequest(id, parameters,graphResultConverter, true);
        }

        public GraphResult<T> MakeGraphPost<T>(
             string id,
             string connection,
             Dictionary<string, string> parameters,
             Func<string,T> graphResultConverter
             )
        {
            return BaseGraphRequest(id + (connection != null ? "/" + connection : string.Empty), parameters,graphResultConverter, true);
        }

        public GraphResult<T> MakeGraphSeach<T>(
            Func<string,T> graphResultConverter,
            string query = null,
            string objectType = null
            )
        {
            var parameters = new Dictionary<string, string>();
            if (query != null) parameters.Add("q", query);
            if (objectType != null) parameters.Add("type", objectType);
            return BaseGraphRequest("search", parameters,graphResultConverter);
        }

        public GraphResult<T> MakeGraphRequest<T>(
             string id,
             Func<string,T> graphResultConverter,
             string connection = null,
             IEnumerable<string> fields = null
             )
        {
            var parameters = (fields != null ? new Dictionary<string, string> { { "fields", fields.Aggregate((x, y) => x = x + "," + y) } } : null);
            return BaseGraphRequest(id + (connection != null ? "/" + connection : string.Empty), parameters,graphResultConverter);
        }

        [OutputCache(VaryByParam = "none", Duration = 0,NoStore = true)]
        public GraphResult<T> MakeGraphRequest<T>(
            IEnumerable<string> ids,
            Func<string,T> graphResultConverter,
            IEnumerable<string> fields = null
            )
        {
            var parameters = new Dictionary<string, string> { { "ids", ids.Aggregate((x, y) => x = x + "," + y) } };
            if (fields != null)
            {
                parameters.Add("fields", fields.Aggregate((x, y) => x = x + "," + y));
            }
            return BaseGraphRequest("", parameters,graphResultConverter);
        }

        public GraphResult<T> BaseGraphRequest<T>(string path, IDictionary<string, string> parameters, Func<string,T> graphResultConverter, bool isPost = false)
        {
            var results = new GraphResult<T>(null,graphResultConverter);
           
            RestSharp.RestClient client;
            RestSharp.RestRequest request;
            GenericGraphRequest(path, parameters,out client,out request, isPost);
            Trace.Write("http request : " + request.ToString());
            var response = client.Execute(request);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                Trace.Write("http response : " + response.Content);
                results = new GraphResult<T>(response.Content, graphResultConverter);
            }
            else
            {
                Trace.TraceWarning("Status Code: " + response.StatusCode + " Content: " + response.Content + " Headers : " + response.Headers);
            }
            return results;
        }

        protected void GenericGraphRequest(string path, IDictionary<string, string> parameters, out RestSharp.RestClient client, out RestSharp.RestRequest request, bool isPost = false)
        {
            GenericGraphRequest(path, parameters, out client, out request, isPost ? Method.POST : Method.GET);
        }

        public void GenericGraphRequest(string path, IDictionary<string, string> parameters, out RestSharp.RestClient client, out RestSharp.RestRequest request, Method method)
        {
            client = new RestSharp.RestClient("https://graph.facebook.com");
            client.FollowRedirects = true;
            var restRequest = new RestSharp.RestRequest(path, method);

            parameters.ForEach(x => restRequest.AddParameter(x.Key, x.Value));
            restRequest.AddParameter("access_token", _facebookCore.AccessToken);

            request = restRequest;
            Trace.Write("AccessToken:" + _facebookCore.AccessToken, "GraphApi.BaseGraphRequest");
            Trace.Write("Path: " + path + " Parameters: " + ((parameters == null || parameters.Count == 0) ? "" : parameters.Select(x => x.Key + "=" + x.Value).Aggregate((x, y) => x = x + " " + y)) + " Method=" + method, "GraphApi.BaseGraphRequest");
        }
    }
}
